#![allow(clippy::ptr_arg)]

#[macro_use]
extern crate clap;

use std::path::Path;

use vhdl_lang::{Config, MessagePrinter};

mod component;
use vhdl2s::vhdl::spinal;
use vhdl2s::vhdl::utils;
use vhdl2s::vhdl::peephole;

fn main() {
    use clap::{App, Arg};

    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(
            Arg::with_name("num-threads")
                .short("-p")
                .long("--num-threads")
                .help("The number of threads to use. By default the maximum is selected based on process cores"),
        )
        .arg(
            Arg::with_name("config")
                .help("Config file in TOML format containing libraries and settings")
                .short("-c")
                .long("--config")
                .required(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("file")
                .help("single file")
                .short("-f")
                .long("--file")
                .takes_value(true),
        )
        .get_matches();

    if matches.is_present("num-threads") {
        let num_threads = value_t_or_exit!(matches.value_of("num-threads"), usize);
        rayon::ThreadPoolBuilder::new()
            .num_threads(num_threads)
            .build_global()
            .unwrap();
    }

    let file_name = value_t_or_exit!(matches.value_of("config"), String);
    let mut config = Config::default();
    let mut msg_printer = MessagePrinter::default();
    config.load_external_config(&mut msg_printer);
    config.append(
        &Config::read_file_path(Path::new(&file_name)).expect("Failed to read config file"),
        &mut msg_printer,
    );

    let project = component::project_parse(&config, &mut msg_printer);
    // for source_file in project.files() {
    //     if let Some(sfext) = source_file.get_source_file().file_name().file_stem() {
    //         let sf = sfext.to_str().unwrap();
    //         if sf == "rru_top_struct" {
    //             let design_file = source_file.get_design_file();
    //             for unit in design_file.design_units {
    //                 let ident = {
    //                     match unit {
    //                         vhdl_lang::ast::AnyDesignUnit::Primary(vhdl_lang::ast::AnyPrimaryUnit::Entity(ed)) => Some(ed.ident),
    //                         _ => None
    //                     }
    //                 };
    //                 if let Some(id) = ident {
    //                     println!("{:?}",id.item.name());
    //                     println!();
    //                 }
    //             }
    //         }
    //     }        
    // }

    let base = spinal::Database::from(&project);

    if let Some(file_name) = matches.value_of("file") {
        let mut result : Vec<String> = Vec::new();
        utils::all_instance(&project,&base,&file_name.to_string(),0,&mut result);
        for line in result{
            println!("{}",line);
        }
        println!("{}",utils::case_class(&project,&base,&file_name.to_string()));
        utils::dump_architecture(&project,&base,&file_name.to_string());
    }
    
    // for en in base.entities() {
    //     println!("{}",en.dumb_case_class(vec![String::new()]));
    // }   
    
    // peephole::reg_test();
    // Exit without running Drop on entire allocated AST
    std::process::exit(0);
}


